##    Copyright 2007 David Blewett
##
##   Licensed under the Apache License, Version 2.0 (the "License");
##   you may not use this file except in compliance with the License.
##   You may obtain a copy of the License at
##
##       http://www.apache.org/licenses/LICENSE-2.0
##
##   Unless required by applicable law or agreed to in writing, software
##   distributed under the License is distributed on an "AS IS" BASIS,
##   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
##   See the License for the specific language governing permissions and
##   limitations under the License.
## Author: David Blewett
## Contact: david@dawninglight.net

"""Message and related objects for the imap object model."""

__all__ = [
    'Message',
    'Address',
    'Envelope',
    ]

from email.Message import Message

class Message(Message):
    """
    Class to contain an IMAP message returned from an FetchCommand.
    
    @type C{int}
    @param uid: The unique identifier associated with this message.
    
    @type C{iterable}
    @param flags: The flags, represented as strings.
    
    @type C{str}
    @param internal_date: An RFC822-formatted date string.
    
    @type C{Message}
    @param msg: An email.Message object.
    """
    def __init__(self, uid, seq, flags=None, internal_date=None, msg=None):
        self.uid = uid
        self.seq = seq
        self.flags = flags
        self.internal_date = internal_date
        #initialize Message object
        Message.__init__(self)
        for i in msg.__dict__:
            #Add attributes from supplied Message object
            if isinstance(i, list):
                self.__dict[i] = msg.__dict[i[:]]
            else:
                self.__dict__[i] = msg.__dict__[i]
        
class Address:
    """
    Class to represent a From/Sender/Reply-To address in an IMAP message
    returned from an FetchCommand.
    
    @type C{list}
    @param address: tuple of string parts of an IMAP address:
        [personal_name, source_route, mailbox_name, host_name]
    
    "David Blewett" <david@dawninglight.net>
    personal_name='David Blewett', source_route=None, mailbox_name='david',
        host_name='dawninglight.net'
    """
    def __init__(self, address):
        self.personal_name = address[0]
        self.source_route = address[1]
        self.mailbox_name = address[2]
        self.host_name = address[3]

    def __str__(self):
        if self.personal_name:
            return '"%s" <%s@%s>' % (self.personal_name, self.mailbox_name, self.host_name)
        else:
            return '<%s@%s>' % (self.mailbox_name, self.host_name)
    
ENV_FIELDS = (
        'date', 'subject', 'msg_from', 'sender', 'reply_to', 'to', 'cc', 'bcc', 
        'in_reply_to', 'msg_id'
      )
ENV_ADDR_FIELDS = (
        'msg_from', 'sender', 'reply_to', 'to', 'cc', 'bcc', 'in_reply_to'
      )
class Envelope:
    """
    Class to represent the envelope structure of an IMAP message returned from
    an FetchCommand.
    @type C{list}
    @param **kwarg
    date, subject, msg_from, sender, reply_to, to, cc, bcc, in_reply_to, msg_id
    Among the accepted keywords are::

        date        : An RFC822-formatted date string.

        subject     : subject of the message.

        msg_from,
        sender,
        reply_to,
        to,
        cc,
        bcc,
        in_reply_to : Instances if Address
        
        msg_id      : Message ID. '4de2b8811ee02d6648f0031fe2ea2d60@www.lulu.com'
    """
    _ENV_FIELD_STR = {
                'date':'Date', 'subject': 'Subject', 'msg_from':'From', 
                'sender':'Sender', 'reply_to':'Reply-To', 'to':'To', 
                'cc':'Cc', 'bcc':'Bcc', 'in_reply_to':'In-Reply-To', 
                'msg_id':'Message-Id'
              }
    def __init__(self, **kwarg):
        self._msg = None
        for f in ENV_FIELDS:
            if f in kwarg.keys():
                self.__dict__[f] = kwarg[f]
            else:
                if f in ENV_ADDR_FIELDS:
                    self.__dict__[f] = []
                else:
                    self.__dict__[f] = None

    def __str__(self):
        return self.parse_envelope().as_string()
        
    def parse_envelope(self):
        if not isinstance(self._msg, Message):
            fields = []
            for i in range(len(ENV_FIELDS)):
                f = ENV_FIELDS[i]
                if f in ENV_ADDR_FIELDS:
                    if self.__dict__[f]:
                        addresses = '; '.join([str(a) for a in self.__dict__[f]])
                    else:
                        addresses = self.__dict__[f]
                    fields.append('%s: %s' % (self._ENV_FIELD_STR[f], addresses))            
                else:
                    fields.append('%s: %s' % (self._ENV_FIELD_STR[f], self.__dict__[f]))
            self._msg = HeaderParser().parsestr('\r\n'.join(fields))
        
        return self._msg